package com.godenwater.recv.server.summit;

import com.godenwater.core.container.BasicModule;
import org.apache.commons.lang3.StringUtils;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.serial.SerialAddress;
import org.apache.mina.transport.serial.SerialAddress.DataBits;
import org.apache.mina.transport.serial.SerialAddress.FlowControl;
import org.apache.mina.transport.serial.SerialAddress.Parity;
import org.apache.mina.transport.serial.SerialAddress.StopBits;
import org.apache.mina.transport.serial.SerialConnector;
import org.apache.mina.transport.socket.DatagramSessionConfig;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioDatagramAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;

public class SummitConnectionManager extends BasicModule {

    private static Logger logger = LoggerFactory
            .getLogger(SummitConnectionManager.class);

    private static int DEFAULT_SERVER_PORT = 5380;
    // 创建一个非阻塞式的服务端，默认打开一个创建此对象
    private NioSocketAcceptor tcpAcceptor;
    private NioDatagramAcceptor udpAcceptor;// = new NioDatagramAcceptor();

    private IoConnector gsmConnector;// = new SerialConnector();
    private IoConnector pstnConnector;// = new SerialConnector();

    public SummitConnectionManager() {
        super("Summit Connection Manager");
    }

    @Override
    public void start() {
        super.start();
        startTcpListener();
        startUdpListener();
        startGsmListener();
    }

    @Override
    public void stop() {
        super.stop();
        stopTcpListener();
        stopUdpListener();
        stopGsmListener();
    }

    public boolean isTcpListenerEnabled() {
        return true;
    }

    public int getTcpListenerPort() {
        return DEFAULT_SERVER_PORT;
    }

    public void setTcpListenerPort(int port) {
        if (port == getTcpListenerPort()) {
            // Ignore new setting
            return;
        }
        stopTcpListener();
        if (isTcpListenerEnabled()) {
            try {
                Thread.sleep(5 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // Start the port listener for s2s communication
            startTcpListener();
        }
    }

    private void startTcpListener() {

        if (SummitConfig.isHydroGprsTcpEnabled()) {

            tcpAcceptor = new NioSocketAcceptor();
            int PORT = SummitConfig.getHydroGprsTcpPort();
            System.out.println(">>SUMMIT tcp port " + PORT);
            // The logger, if needed. Commented atm
            DefaultIoFilterChainBuilder chain = tcpAcceptor.getFilterChain();
            // chain.addLast("logger", new LoggingFilter());
            chain.addLast("protocol", new ProtocolCodecFilter(new SummitServerCodecFactory(
                    "tcp")));

            // 增加一个数据处理缓存线程池
            // chain.addLast("dbThreadpool", new
            // ExecutorFilter(Executors.newCachedThreadPool()));

            // LoggingFilter loggingFilter = new LoggingFilter();
            // chain.addLast("logging", loggingFilter);

            tcpAcceptor.setHandler(new SummitServerDataHandler(SummitServer.getInstance(),
                    "GPRS"));
            // 设置读取数据的缓冲区大小
            tcpAcceptor.getSessionConfig().setReadBufferSize(1024); // 针对最大报文的缓冲设置

            // 读写通道30秒内无操作进入空闲状态
            tcpAcceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30);

            SocketSessionConfig dcfg = tcpAcceptor.getSessionConfig();
            dcfg.setReuseAddress(true);

            try {
//新加代码
                String ip = SummitConfig.getHydroGprsTcpIp();
                if (StringUtils.isBlank(ip) || StringUtils.equals(ip, "0")) {
                    tcpAcceptor.bind(new InetSocketAddress(PORT));
                } else {
                    InetAddress inetAddress = InetAddress.getByName(ip);
                    tcpAcceptor.bind(new InetSocketAddress(inetAddress, PORT));
                }
//------------------------------------------------------
                //tcpAcceptor.bind(new InetSocketAddress(PORT));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private void stopTcpListener() {
        if (tcpAcceptor != null) {
            System.out.println("正在关闭TCP连接");
            tcpAcceptor.unbind();
            tcpAcceptor = null;
        }
    }

    // ---------------------------------------------

    private void startUdpListener() {

        if (SummitConfig.isHydroGprsUdpEnabled()) {

            int PORT = SummitConfig.getHydroGprsUdpPort();
            System.out.println(">> udp port " + PORT);
            udpAcceptor = new NioDatagramAcceptor();

            // The logger, if needed. Commented atm
            DefaultIoFilterChainBuilder chain = udpAcceptor.getFilterChain();
            chain.addLast("protocol", new ProtocolCodecFilter(new SummitServerCodecFactory(
                    "udp")));

            // 增加一个数据处理缓存线程池
            // chain.addLast("dbThreadpool", new
            // ExecutorFilter(Executors.newCachedThreadPool()));

            // chain.addLast("logging", new LoggingFilter());

            udpAcceptor.setHandler(new SummitServerDataHandler(SummitServer.getInstance(),
                    "udp"));
            // 设置读取数据的缓冲区大小
            udpAcceptor.getSessionConfig().setReadBufferSize(1024);
            // 读写通道30秒内无操作进入空闲状态
            udpAcceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30);

            DatagramSessionConfig dcfg = udpAcceptor.getSessionConfig();
            dcfg.setReuseAddress(true);
            try {

                String ip = SummitConfig.getHydroGprsUdpIp();
                if (StringUtils.isBlank(ip) || StringUtils.equals(ip, "0")) {
                    udpAcceptor.bind(new InetSocketAddress(PORT));
                } else {
                    InetAddress inetAddress = InetAddress.getByName(ip);
                    udpAcceptor.bind(new InetSocketAddress(inetAddress, PORT));
                }
                //udpAcceptor.bind(new InetSocketAddress(PORT));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }

    private void stopUdpListener() {
        if (udpAcceptor != null) {
            udpAcceptor.unbind();
            udpAcceptor = null;
        }
    }


    //-------------------------------------------
    private void startGsmListener() {

        if (SummitConfig.isHydroGsmEnabled()) {
            gsmConnector = new SerialConnector();
            // /dev/ttyS0

            DataBits db = DataBits.DATABITS_8;
            int dataBits = SummitConfig.getHydroGsmByteSize();
            if (dataBits == 5) {
                db = DataBits.DATABITS_5;
            }
            if (dataBits == 6) {
                db = DataBits.DATABITS_6;
            }
            if (dataBits == 7) {
                db = DataBits.DATABITS_7;
            }

            Parity p = Parity.NONE;
            String parity = SummitConfig.getHydroGsmParity();
            if (StringUtils.equalsIgnoreCase(parity, "Even")) {
                p = Parity.EVEN;
            }
            if (StringUtils.equalsIgnoreCase(parity, "Odd")) {
                p = Parity.ODD;
            }
            if (StringUtils.equalsIgnoreCase(parity, "Mark")) {
                p = Parity.MARK;
            }
            if (StringUtils.equalsIgnoreCase(parity, "Space")) {
                p = Parity.SPACE;
            }

            StopBits sb = StopBits.BITS_1;
            String stopBits = SummitConfig.getHydroGsmStopbits();
            if (StringUtils.equalsIgnoreCase(stopBits, "1.5")) {
                sb = StopBits.BITS_1_5;
            }
            if (StringUtils.equalsIgnoreCase(parity, "2")) {
                sb = StopBits.BITS_2;
            }

            SerialAddress portAddress = new SerialAddress(
                    SummitConfig.getHydroGsmSerial(),
                    SummitConfig.getHydroGsmBaudRate(), db, sb, p,
                    FlowControl.NONE);

            // ==========================================

            DefaultIoFilterChainBuilder chain = gsmConnector.getFilterChain();
            // chain.addLast("logger", new LoggingFilter());
            chain.addLast("protocol", new ProtocolCodecFilter(
                    new SummitServerCodecFactory("gsm")));

            // 增加一个数据处理缓存线程池
            // chain.addLast("dbThreadpool", new
            // ExecutorFilter(Executors.newCachedThreadPool()));

            // LoggingFilter loggingFilter = new LoggingFilter();
            // chain.addLast("logging", loggingFilter);

            gsmConnector.setHandler(new SummitServerDataHandler(SummitServer
                    .getInstance(), "COMM"));
            // 设置读取数据的缓冲区大小
            gsmConnector.getSessionConfig().setReadBufferSize(1024); // 针对最大报文的缓冲设置

            // 读写通道30秒内无操作进入空闲状态
            gsmConnector.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,
                    40);

            // ===========================================

            try {
                ConnectFuture future = gsmConnector.connect(portAddress);

                future.await();

                // IoSession sessin = future.getSession();

            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void stopGsmListener() {
        if (gsmConnector != null) {
            gsmConnector.dispose();
            gsmConnector = null;
        }
    }

    public static void main(String[] args) {
        SerialConnector connector = new SerialConnector();

        DefaultIoFilterChainBuilder chain = connector.getFilterChain();
        chain.addLast("protocol", new ProtocolCodecFilter(new SummitServerCodecFactory(
                "test")));
        LoggingFilter loggingFilter = new LoggingFilter();
        connector.getFilterChain().addLast("logging", loggingFilter);

    }
}
